/*
 * Copyright 2011 Katsunori Koyanagi
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package sweezy.swf.utils
{
	import flash.utils.ByteArray;
	import sweezy.core.reflect.IProperty;
	import sweezy.core.reflect.IType;
	import sweezy.core.reflect.Reflection;
	import sweezy.swf.IElement;

	public class CloneUtils
	{

		public static function clone(value:*):*
		{
			if (value === null)
			{
				return null;
			}
			if (value is String)
			{
				return value;
			}
			if (value is Boolean)
			{
				return value;
			}
			if (value is uint)
			{
				return value;
			}
			if (value is int)
			{
				return value;
			}
			if (value is Array)
			{
				return cloneArray(value as Array);
			}
			if (value is ByteArray)
			{
				return cloneByteArray(value as ByteArray);
			}
			if (value is IElement)
			{
				return (value as IElement).clone();
			}

			return null;
		}

		public static function createClone(target:IElement):IElement
		{
			if (target === null)
			{
				return null;
			}

			var type:IType = Reflection.forInstance(target);
			var result:IElement = type.newInstance();

			for each (var property:IProperty in type.properties)
			{
				if (!property.isVariable)
				{
					continue;
				}
				if (property.isStatic)
				{
					continue;
				}
				if (property.isConst)
				{
					continue;
				}

				result[property.name] = clone(target[property.name]);
			}

			return result;
		}

		private static function cloneArray(target:Array):Array
		{
			if (target === null)
			{
				return null;
			}

			var result:Array = new Array(target.length);
			for (var i:uint = 0, len:uint = target.length; i < len; i++)
			{
				result[i] = clone(target[i]);
			}

			return result;
		}

		private static function cloneByteArray(target:ByteArray):ByteArray
		{
			if (target === null)
			{
				return null;
			}

			var position:uint = target.position;
			target.position = 0;

			var result:ByteArray = new ByteArray();
			result.writeBytes(target);

			result.endian = target.endian;
			result.position = position;
			target.position = position;

			return result;
		}
	}
}
